home *** CD-ROM | disk | FTP | other *** search
/ Skunkware 5 / Skunkware 5.iso / lib / emacs / 19.22 / lisp / replace.el < prev    next >
Lisp/Scheme  |  1993-11-10  |  22KB  |  582 lines

  1. ;;; replace.el --- replace commands for Emacs.
  2.  
  3. ;; Copyright (C) 1985, 1986, 1987, 1992 Free Software Foundation, Inc.
  4.  
  5. ;; This file is part of GNU Emacs.
  6.  
  7. ;; GNU Emacs is free software; you can redistribute it and/or modify
  8. ;; it under the terms of the GNU General Public License as published by
  9. ;; the Free Software Foundation; either version 2, or (at your option)
  10. ;; any later version.
  11.  
  12. ;; GNU Emacs is distributed in the hope that it will be useful,
  13. ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15. ;; GNU General Public License for more details.
  16.  
  17. ;; You should have received a copy of the GNU General Public License
  18. ;; along with GNU Emacs; see the file COPYING.  If not, write to
  19. ;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
  20.  
  21. ;;; Commentary:
  22.  
  23. ;; This package supplies the string and regular-expression replace functions
  24. ;; documented in the Emacs user's manual.
  25.  
  26. ;;; Code:
  27.  
  28. (defconst case-replace t "\
  29. *Non-nil means query-replace should preserve case in replacements.")
  30.  
  31. (defvar query-replace-history nil)
  32.  
  33. (defun query-replace-read-args (string)
  34.   (let (from to)
  35.     (setq from (read-from-minibuffer (format "%s: " string)
  36.                      nil nil nil
  37.                      'query-replace-history))
  38.     (setq to (read-from-minibuffer (format "%s %s with: " string from)
  39.                    nil nil nil
  40.                    'query-replace-history))
  41.     (list from to current-prefix-arg)))
  42.  
  43. (defun query-replace (from-string to-string &optional arg)
  44.   "Replace some occurrences of FROM-STRING with TO-STRING.
  45. As each match is found, the user must type a character saying
  46. what to do with it.  For directions, type \\[help-command] at that time.
  47.  
  48. Preserves case in each replacement if  case-replace  and  case-fold-search
  49. are non-nil and FROM-STRING has no uppercase letters.
  50. Third arg DELIMITED (prefix arg if interactive) non-nil means replace
  51. only matches surrounded by word boundaries.
  52.  
  53. To customize possible responses, change the \"bindings\" in `query-replace-map'."
  54.   (interactive (query-replace-read-args "Query replace"))
  55.   (perform-replace from-string to-string t nil arg)
  56.   (or unread-command-events (message "Done")))
  57. (define-key esc-map "%" 'query-replace)
  58.  
  59. (defun query-replace-regexp (regexp to-string &optional arg)
  60.   "Replace some things after point matching REGEXP with TO-STRING.
  61. As each match is found, the user must type a character saying
  62. what to do with it.  For directions, type \\[help-command] at that time.
  63.  
  64. Preserves case in each replacement if  case-replace  and  case-fold-search
  65. are non-nil and REGEXP has no uppercase letters.
  66. Third arg DELIMITED (prefix arg if interactive) non-nil means replace
  67. only matches surrounded by word boundaries.
  68. In TO-STRING, \\& means insert what matched REGEXP,
  69. and \\=\\<n> means insert what matched <n>th \\(...\\) in REGEXP."
  70.   (interactive (query-replace-read-args "Query replace regexp"))
  71.   (perform-replace regexp to-string t t arg)
  72.   (or unread-command-events (message "Done")))
  73.  
  74. (defun map-query-replace-regexp (regexp to-strings &optional arg)
  75.   "Replace some matches for REGEXP with various strings, in rotation.
  76. The second argument TO-STRINGS contains the replacement strings, separated
  77. by spaces.  This command works like `query-replace-regexp' except
  78. that each successive replacement uses the next successive replacement string,
  79. wrapping around from the last such string to the first.
  80.  
  81. Non-interactively, TO-STRINGS may be a list of replacement strings.
  82.  
  83. A prefix argument N says to use each replacement string N times
  84. before rotating to the next."
  85.   (interactive
  86.    (let (from to)
  87.      (setq from (read-from-minibuffer "Map query replace (regexp): "
  88.                       nil nil nil
  89.                       'query-replace-history))
  90.      (setq to (read-from-minibuffer
  91.            (format "Query replace %s with (space-separated strings): "
  92.                from)
  93.            nil nil nil
  94.            'query-replace-history))
  95.      (list from to current-prefix-arg)))
  96.   (let (replacements)
  97.     (if (listp to-strings)
  98.     (setq replacements to-strings)
  99.       (while (/= (length to-strings) 0)
  100.     (if (string-match " " to-strings)
  101.         (setq replacements
  102.           (append replacements
  103.               (list (substring to-strings 0
  104.                        (string-match " " to-strings))))
  105.           to-strings (substring to-strings
  106.                        (1+ (string-match " " to-strings))))
  107.       (setq replacements (append replacements (list to-strings))
  108.         to-strings ""))))
  109.     (perform-replace regexp replacements t t nil arg))
  110.   (or unread-command-events (message "Done")))
  111.  
  112. (defun replace-string (from-string to-string &optional delimited)
  113.   "Replace occurrences of FROM-STRING with TO-STRING.
  114. Preserve case in each match if `case-replace' and `case-fold-search'
  115. are non-nil and FROM-STRING has no uppercase letters.
  116. Third arg DELIMITED (prefix arg if interactive) non-nil means replace
  117. only matches surrounded by word boundaries.
  118.  
  119. This function is usually the wrong thing to use in a Lisp program.
  120. What you probably want is a loop like this:
  121.   (while (search-forward OLD-STRING nil t)
  122.     (replace-match REPLACEMENT nil t))
  123. which will run faster and will not set the mark or print anything."
  124.   (interactive (query-replace-read-args "Replace string"))
  125.   (perform-replace from-string to-string nil nil delimited)
  126.   (or unread-command-events (message "Done")))
  127.  
  128. (defun replace-regexp (regexp to-string &optional delimited)
  129.   "Replace things after point matching REGEXP with TO-STRING.
  130. Preserve case in each match if case-replace and case-fold-search
  131. are non-nil and REGEXP has no uppercase letters.
  132. Third arg DELIMITED (prefix arg if interactive) non-nil means replace
  133. only matches surrounded by word boundaries.
  134. In TO-STRING, \\& means insert what matched REGEXP,
  135. and \\=\\<n> means insert what matched <n>th \\(...\\) in REGEXP.
  136.  
  137. This function is usually the wrong thing to use in a Lisp program.
  138. What you probably want is a loop like this:
  139.   (while (re-search-forward REGEXP nil t)
  140.     (replace-match REPLACEMENT nil nil))
  141. which will run faster and will not set the mark or print anything."
  142.   (interactive (query-replace-read-args "Replace regexp"))
  143.   (perform-replace regexp to-string nil t delimited)
  144.   (or unread-command-events (message "Done")))
  145.  
  146. (defvar regexp-history nil
  147.   "History list for some commands that read regular expressions.")
  148.  
  149. (defalias 'delete-non-matching-lines 'keep-lines)
  150. (defun keep-lines (regexp)
  151.   "Delete all lines except those containing matches for REGEXP.
  152. A match split across lines preserves all the lines it lies in.
  153. Applies to all lines after point."
  154.   (interactive (list (read-from-minibuffer
  155.               "Keep lines (containing match for regexp): "
  156.               nil nil nil 'regexp-history)))
  157.   (save-excursion
  158.     (or (bolp) (forward-line 1))
  159.     (let ((start (point)))
  160.       (while (not (eobp))
  161.     ;; Start is first char not preserved by previous match.
  162.     (if (not (re-search-forward regexp nil 'move))
  163.         (delete-region start (point-max))
  164.       (let ((end (save-excursion (goto-char (match-beginning 0))
  165.                      (beginning-of-line)
  166.                      (point))))
  167.         ;; Now end is first char preserved by the new match.
  168.         (if (< start end)
  169.         (delete-region start end))))
  170.     (setq start (save-excursion (forward-line 1)
  171.                     (point)))
  172.     ;; If the match was empty, avoid matching again at same place.
  173.     (and (not (eobp)) (= (match-beginning 0) (match-end 0))
  174.          (forward-char 1))))))
  175.  
  176. (defalias 'delete-matching-lines 'flush-lines)
  177. (defun flush-lines (regexp)
  178.   "Delete lines containing matches for REGEXP.
  179. If a match is split across lines, all the lines it lies in are deleted.
  180. Applies to lines after point."
  181.   (interactive (list (read-from-minibuffer
  182.               "Flush lines (containing match for regexp): "
  183.               nil nil nil 'regexp-history)))
  184.   (save-excursion
  185.     (while (and (not (eobp))
  186.         (re-search-forward regexp nil t))
  187.       (delete-region (save-excursion (goto-char (match-beginning 0))
  188.                      (beginning-of-line)
  189.                      (point))
  190.              (progn (forward-line 1) (point))))))
  191.  
  192. (defalias 'count-matches 'how-many)
  193. (defun how-many (regexp)
  194.   "Print number of matches for REGEXP following point."
  195.   (interactive (list (read-from-minibuffer
  196.               "How many matches for (regexp): "
  197.               nil nil nil 'regexp-history)))
  198.   (let ((count 0) opoint)
  199.     (save-excursion
  200.      (while (and (not (eobp))
  201.          (progn (setq opoint (point))
  202.             (re-search-forward regexp nil t)))
  203.        (if (= opoint (point))
  204.        (forward-char 1)
  205.      (setq count (1+ count))))
  206.      (message "%d occurrences" count))))
  207.  
  208. (defvar occur-mode-map ())
  209. (if occur-mode-map
  210.     ()
  211.   (setq occur-mode-map (make-sparse-keymap))
  212.   (define-key occur-mode-map "\C-c\C-c" 'occur-mode-goto-occurrence))
  213.  
  214. (defvar occur-buffer nil)
  215. (defvar occur-nlines nil)
  216. (defvar occur-pos-list nil)
  217.  
  218. (defun occur-mode ()
  219.   "Major mode for output from \\[occur].
  220. Move point to one of the occurrences in this buffer,
  221. then use \\[occur-mode-goto-occurrence] to go to the same occurrence
  222. in the buffer that the occurrences were found in.
  223. \\{occur-mode-map}"
  224.   (kill-all-local-variables)
  225.   (use-local-map occur-mode-map)
  226.   (setq major-mode 'occur-mode)
  227.   (setq mode-name "Occur")
  228.   (make-local-variable 'occur-buffer)
  229.   (make-local-variable 'occur-nlines)
  230.   (make-local-variable 'occur-pos-list)
  231.   (run-hooks 'occur-mode-hook))
  232.  
  233. (defun occur-mode-goto-occurrence ()
  234.   "Go to the line this occurrence was found in, in the buffer it was found in."
  235.   (interactive)
  236.   (if (or (null occur-buffer)
  237.       (null (buffer-name occur-buffer)))
  238.       (progn
  239.     (setq occur-buffer nil
  240.           occur-pos-list nil)
  241.     (error "Buffer in which occurrences were found is deleted")))
  242.   (let* ((occur-number (save-excursion
  243.              (beginning-of-line)
  244.              (/ (1- (count-lines (point-min)
  245.                          (save-excursion
  246.                            (beginning-of-line)
  247.                            (point))))
  248.                 (cond ((< occur-nlines 0)
  249.                    (- 2 occur-nlines))
  250.                   ((> occur-nlines 0)
  251.                    (+ 2 (* 2 occur-nlines)))
  252.                   (t 1)))))
  253.      (pos (nth occur-number occur-pos-list)))
  254.     (or pos
  255.     (error "No occurrence on this line"))
  256.     (pop-to-buffer occur-buffer)
  257.     (goto-char (marker-position pos))))
  258.  
  259. (defvar list-matching-lines-default-context-lines 0
  260.   "*Default number of context lines to include around a `list-matching-lines'
  261. match.  A negative number means to include that many lines before the match.
  262. A positive number means to include that many lines both before and after.")
  263.  
  264. (defalias 'list-matching-lines 'occur)
  265.  
  266. (defun occur (regexp &optional nlines)
  267.   "Show all lines in the current buffer containing a match for REGEXP.
  268.  
  269. If a match spreads across multiple lines, all those lines are shown.
  270.  
  271. Each line is displayed with NLINES lines before and after, or -NLINES
  272. before if NLINES is negative.
  273. NLINES defaults to `list-matching-lines-default-context-lines'.
  274. Interactively it is the prefix arg.
  275.  
  276. The lines are shown in a buffer named `*Occur*'.
  277. It serves as a menu to find any of the occurrences in this buffer.
  278. \\[describe-mode] in that buffer will explain how."
  279.   (interactive (list (let* ((default (car regexp-history))
  280.                 (input 
  281.                  (read-from-minibuffer
  282.                   (if default
  283.                   (format "List lines matching regexp (default `%s'): " default)
  284.                 "List lines matching regexp: ")
  285.                   nil nil nil
  286.                   'regexp-history)))
  287.                (if (> (length input) 0) input
  288.              (setcar regexp-history default)))
  289.              current-prefix-arg))
  290.   (setq nlines (if nlines (prefix-numeric-value nlines)
  291.          list-matching-lines-default-context-lines))
  292.   (let ((first t)
  293.     (buffer (current-buffer))
  294.     (linenum 1)
  295.     (prevpos (point-min))
  296.     (final-context-start (make-marker)))
  297. ;;;    (save-excursion
  298. ;;;      (beginning-of-line)
  299. ;;;      (setq linenum (1+ (count-lines (point-min) (point))))
  300. ;;;      (setq prevpos (point)))
  301.     (with-output-to-temp-buffer "*Occur*"
  302.       (save-excursion
  303.     (set-buffer standard-output)
  304.     (insert "Lines matching ")
  305.     (prin1 regexp)
  306.     (insert " in buffer " (buffer-name buffer) ?. ?\n)
  307.     (occur-mode)
  308.     (setq occur-buffer buffer)
  309.     (setq occur-nlines nlines)
  310.     (setq occur-pos-list ()))
  311.       (if (eq buffer standard-output)
  312.       (goto-char (point-max)))
  313.       (save-excursion
  314.     (beginning-of-buffer)
  315.     ;; Find next match, but give up if prev match was at end of buffer.
  316.     (while (and (not (= prevpos (point-max)))
  317.             (re-search-forward regexp nil t))
  318.       (goto-char (match-beginning 0))
  319.       (beginning-of-line)
  320.       (save-match-data
  321.         (setq linenum (+ linenum (count-lines prevpos (point)))))
  322.       (setq prevpos (point))
  323.       (goto-char (match-end 0))
  324.       (let* ((start (save-excursion
  325.               (goto-char (match-beginning 0))
  326.               (forward-line (if (< nlines 0) nlines (- nlines)))
  327.               (point)))
  328.          (end (save-excursion
  329.             (goto-char (match-end 0))
  330.             (if (> nlines 0)
  331.                 (forward-line (1+ nlines))
  332.                 (forward-line 1))
  333.             (point)))
  334.          (tag (format "%3d" linenum))
  335.          (empty (make-string (length tag) ?\ ))
  336.          tem)
  337.         (save-excursion
  338.           (setq tem (make-marker))
  339.           (set-marker tem (point))
  340.           (set-buffer standard-output)
  341.           (setq occur-pos-list (cons tem occur-pos-list))
  342.           (or first (zerop nlines)
  343.           (insert "--------\n"))
  344.           (setq first nil)
  345.           (insert-buffer-substring buffer start end)
  346.           (backward-char (- end start))
  347.           (setq tem nlines)
  348.           (while (> tem 0)
  349.         (insert empty ?:)
  350.         (forward-line 1)
  351.         (setq tem (1- tem)))
  352.           (let ((this-linenum linenum))
  353.         (set-marker final-context-start
  354.                 (+ (point) (- (match-end 0) (match-beginning 0))))
  355.         (while (< (point) final-context-start)
  356.           (if (null tag)
  357.               (setq tag (format "%3d" this-linenum)))
  358.           (insert tag ?:)
  359.           (setq tag nil)
  360.           (forward-line 1)
  361.           (setq this-linenum (1+ this-linenum))))
  362.           (while (< tem nlines)
  363.         (insert empty ?:)
  364.         (forward-line 1)
  365.         (setq tem (1+ tem))))                
  366.         (forward-line 1)))
  367.     (set-buffer standard-output)
  368.     ;; Put positions in increasing order to go with buffer.
  369.     (setq occur-pos-list (nreverse occur-pos-list))
  370.     (if (interactive-p)
  371.         (message "%d matching lines." (length occur-pos-list)))))))
  372.  
  373. ;; It would be nice to use \\[...], but there is no reasonable way
  374. ;; to make that display both SPC and Y.
  375. (defconst query-replace-help
  376.   "Type Space or `y' to replace one match, Delete or `n' to skip to next,
  377. ESC or `q' to exit, Period to replace one match and exit,
  378. Comma to replace but not move point immediately,
  379. C-r to enter recursive edit (\\[exit-recursive-edit] to get out again),
  380. C-w to delete match and recursive edit,
  381. C-l to clear the screen, redisplay, and offer same replacement again,
  382. ! to replace all remaining matches with no more questions,
  383. ^ to move point back to previous match."
  384.   "Help message while in query-replace")
  385.  
  386. (defvar query-replace-map (make-sparse-keymap)
  387.   "Keymap that defines the responses to questions in `query-replace'.
  388. The \"bindings\" in this map are not commands; they are answers.
  389. The valid answers include `act', `skip', `act-and-show',
  390. `exit', `act-and-exit', `edit', `delete-and-edit', `recenter',
  391. `automatic', `backup', and `help'.")
  392.  
  393. (define-key query-replace-map " " 'act)
  394. (define-key query-replace-map "\d" 'skip)
  395. (define-key query-replace-map [delete] 'skip)
  396. (define-key query-replace-map [backspace] 'skip)
  397. (define-key query-replace-map "y" 'act)
  398. (define-key query-replace-map "n" 'skip)
  399. (define-key query-replace-map "," 'act-and-show)
  400. (define-key query-replace-map "\e" 'exit)
  401. (define-key query-replace-map [escape] 'exit)
  402. (define-key query-replace-map "q" 'exit)
  403. (define-key query-replace-map "\r" 'exit)
  404. (define-key query-replace-map [return] 'exit)
  405. (define-key query-replace-map "." 'act-and-exit)
  406. (define-key query-replace-map "\C-r" 'edit)
  407. (define-key query-replace-map "\C-w" 'delete-and-edit)
  408. (define-key query-replace-map "\C-l" 'recenter)
  409. (define-key query-replace-map "!" 'automatic)
  410. (define-key query-replace-map "^" 'backup)
  411. (define-key query-replace-map "\C-h" 'help)
  412. (define-key query-replace-map "?" 'help)
  413. (define-key query-replace-map "\C-g" 'quit)
  414. (define-key query-replace-map "\C-]" 'quit)
  415.  
  416. (defun perform-replace (from-string replacements
  417.                 query-flag regexp-flag delimited-flag
  418.             &optional repeat-count map)
  419.   "Subroutine of `query-replace'.  Its complexity handles interactive queries.
  420. Don't use this in your own program unless you want to query and set the mark
  421. just as `query-replace' does.  Instead, write a simple loop like this:
  422.   (while (re-search-forward \"foo[ \t]+bar\" nil t)
  423.     (replace-match \"foobar\" nil nil))
  424. which will run faster and do exactly what you probably want."
  425.   (or map (setq map query-replace-map))
  426.   (let ((nocasify (not (and case-fold-search case-replace
  427.                 (string-equal from-string
  428.                       (downcase from-string)))))
  429.     (literal (not regexp-flag))
  430.     (search-function (if regexp-flag 're-search-forward 'search-forward))
  431.     (search-string from-string)
  432.     (real-match-data nil)        ; the match data for the current match
  433.     (next-replacement nil)
  434.     (replacement-index 0)
  435.     (keep-going t)
  436.     (stack nil)
  437.     (next-rotate-count 0)
  438.     (replace-count 0)
  439.     (lastrepl nil)            ;Position after last match considered.
  440.     (match-again t))
  441.     (if (stringp replacements)
  442.     (setq next-replacement replacements)
  443.       (or repeat-count (setq repeat-count 1)))
  444.     (if delimited-flag
  445.     (setq search-function 're-search-forward
  446.           search-string (concat "\\b"
  447.                     (if regexp-flag from-string
  448.                       (regexp-quote from-string))
  449.                     "\\b")))
  450.     (push-mark)
  451.     (undo-boundary)
  452.     ;; Loop finding occurrences that perhaps should be replaced.
  453.     (while (and keep-going
  454.         (not (eobp))
  455.         (funcall search-function search-string nil t)
  456.         ;; If the search string matches immediately after
  457.         ;; the previous match, but it did not match there
  458.         ;; before the replacement was done, ignore the match.
  459.         (if (or (eq lastrepl (point))
  460.             (and regexp-flag
  461.                  (eq lastrepl (match-beginning 0))
  462.                  (not match-again)))
  463.             (if (eobp)
  464.             nil
  465.               ;; Don't replace the null string 
  466.               ;; right after end of previous replacement.
  467.               (forward-char 1)
  468.               (funcall search-function search-string nil t))
  469.           t))
  470.  
  471.       ;; Save the data associated with the real match.
  472.       (setq real-match-data (match-data))
  473.  
  474.       ;; Before we make the replacement, decide whether the search string
  475.       ;; can match again just after this match.
  476.       (if regexp-flag
  477.       (setq match-again (looking-at search-string)))
  478.       ;; If time for a change, advance to next replacement string.
  479.       (if (and (listp replacements)
  480.            (= next-rotate-count replace-count))
  481.       (progn
  482.         (setq next-rotate-count
  483.           (+ next-rotate-count repeat-count))
  484.         (setq next-replacement (nth replacement-index replacements))
  485.         (setq replacement-index (% (1+ replacement-index) (length replacements)))))
  486.       (if (not query-flag)
  487.       (progn
  488.         (store-match-data real-match-data)
  489.         (replace-match next-replacement nocasify literal)
  490.         (setq replace-count (1+ replace-count)))
  491.     (undo-boundary)
  492.     (let (done replaced key def)
  493.       ;; Loop reading commands until one of them sets done,
  494.       ;; which means it has finished handling this occurrence.
  495.       (while (not done)
  496.         (message "Query replacing %s with %s: "
  497.              from-string next-replacement)
  498.         (setq key (read-event))
  499.         (setq key (vector key))
  500.         (setq def (lookup-key map key))
  501.         ;; Restore the match data while we process the command.
  502.         (store-match-data real-match-data)
  503.         (cond ((eq def 'help)
  504.            (with-output-to-temp-buffer "*Help*"
  505.              (princ
  506.               (concat "Query replacing "
  507.                   (if regexp-flag "regexp " "")
  508.                   from-string " with "
  509.                   next-replacement ".\n\n"
  510.                   (substitute-command-keys
  511.                    query-replace-help)))))
  512.           ((eq def 'exit)
  513.            (setq keep-going nil)
  514.            (setq done t))
  515.           ((eq def 'backup)
  516.            (let ((elt (car stack)))
  517.              (goto-char (car elt))
  518.              (setq replaced (eq t (cdr elt)))
  519.              (or replaced
  520.              (store-match-data (cdr elt)))
  521.              (setq stack (cdr stack))))             
  522.           ((eq def 'act)
  523.            (or replaced
  524.                (replace-match next-replacement nocasify literal))
  525.            (setq done t replaced t))
  526.           ((eq def 'act-and-exit)
  527.            (or replaced
  528.                (replace-match next-replacement nocasify literal))
  529.            (setq keep-going nil)
  530.            (setq done t replaced t))
  531.           ((eq def 'act-and-show)
  532.            (if (not replaced)
  533.                (progn
  534.              (replace-match next-replacement nocasify literal)
  535.              (setq replaced t))))
  536.           ((eq def 'automatic)
  537.            (or replaced
  538.                (replace-match next-replacement nocasify literal))
  539.            (setq done t query-flag nil replaced t))
  540.           ((eq def 'skip)
  541.            (setq done t))
  542.           ((eq def 'recenter)
  543.            (recenter nil))
  544.           ((eq def 'edit)
  545.            (store-match-data
  546.             (prog1 (match-data)
  547.               (save-excursion (recursive-edit))))
  548.            ;; Before we make the replacement,
  549.            ;; decide whether the search string
  550.            ;; can match again just after this match.
  551.            (if regexp-flag
  552.                (setq match-again (looking-at search-string))))
  553.           ((eq def 'delete-and-edit)
  554.            (delete-region (match-beginning 0) (match-end 0))
  555.            (store-match-data
  556.             (prog1 (match-data)
  557.               (save-excursion (recursive-edit))))
  558.            (setq replaced t))
  559.           (t
  560.            (setq keep-going nil)
  561.            (setq unread-command-events
  562.              (append (listify-key-sequence key)
  563.                  unread-command-events))
  564.            (setq done t))))
  565.       ;; Record previous position for ^ when we move on.
  566.       ;; Change markers to numbers in the match data
  567.       ;; since lots of markers slow down editing.
  568.       (setq stack
  569.         (cons (cons (point)
  570.                 (or replaced
  571.                 (mapcar
  572.                  (function (lambda (elt)
  573.                          (and elt
  574.                           (marker-position elt))))
  575.                  (match-data))))
  576.               stack))
  577.       (if replaced (setq replace-count (1+ replace-count)))))
  578.       (setq lastrepl (point)))
  579.   (and keep-going stack)))
  580.  
  581. ;;; replace.el ends here
  582.